/* Just temporary */
//TODO: Move to CPP language abstraction
#include "Keywords.h"

#include "StringOps.h"
#include<string>
#include<set>

using namespace std;

bool Keywords::isDataTypeDefiner(const std::string& s)
{
	static char* asKeywords[] = {
		"class",
		"enum",
		"namespace",
		"struct",
		"typedef",
		"union"
	};
	static std::set<char*, LessThan>	asCheckSet(asKeywords, asKeywords + (sizeof(asKeywords)/sizeof(char*)));	

	if(0 != asCheckSet.count((char*)s.c_str())) 
		return true;

	return false;

}

bool Keywords::isBlockKeyword(const std::string& s)
{
	static char* asKeywords[] = {
		"catch",
		"class",
		"do",
		"else",
		"enum",
		"for",
		"if",
		"namespace",
		"struct",
		"switch",
		"template",
		"throw",
		"try",
		"while"
	};
	static std::set<char*, LessThan>	asCheckSet(asKeywords, asKeywords + (sizeof(asKeywords)/sizeof(char*)));	

	if(0 != asCheckSet.count((char*)s.c_str())) 
		return true;

	return false;
}

bool Keywords::isKeyword(const std::string& s)
{
	static char* asKeywords[] = {
		"and",
		"and_eq",
		"asm",
		"auto",
		"bitand",
		"bitor",
		"bool",
		"break",
		"case",
		"catch",
		"char",
		"class",
		"compl",
		"const",
		"const_cast",
		"continue",
		"default",
		"delete",
		"do",
		"double",
		"dynamic_cast",
		"else",
		"enum",
		"explicit",
		"export",
		"extern",
		"false",
		"float",
		"for",
		"friend",
		"goto",
		"if",
		"inline",
		"int",
		"long",
		"mutable",
		"namespace",
		"new",
		"not",
		"not_eq",
		"operator",
		"or",
		"or_eq",
		"private",
		"protected",
		"public",
		"register",
		"reinterpret_cast",
		"return",
		"short",
		"signed",
		"sizeof",
		"static",
		"static_cast",
		"struct",
		"switch",
		"template",
		"this",
		"throw",
		"true",
		"try",
		"typedef",
		"typeid",
		"typename",
		"union",
		"unsigned",
		"using",
		"virtual",
		"void",
		"volatile",
		"wchar_t",
		"while",
		"xor",
		"xor_eq"
	};
	static std::set<char*, LessThan>	asCheckSet(asKeywords, asKeywords + (sizeof(asKeywords)/sizeof(char*)));	

	if(0 != asCheckSet.count((char*)s.c_str())) 
		return true;

	return false;
}

bool Keywords::isPreprocessorKeyword (const string& s)
{
	static char* asKeywords[] = {
		"define",
		"elif",
		"else",
		"endif",
		"error",
		"if",
		"ifdef",
		"ifndef",
		"include",
		"line",
		"pragma",
		"undef"
	};
	static std::set<char*, LessThan>	asCheckSet(asKeywords, asKeywords + (sizeof(asKeywords)/sizeof(char*)));	

	if(0 != asCheckSet.count((char*)s.c_str())) 
		return true;

	return false;
}

bool Keywords::isReturn (const string& s)
{
	static char* asKeywords[] = {
		"return",
		"throw"
	};
	static std::set<char*, LessThan>	asCheckSet(asKeywords, asKeywords + (sizeof(asKeywords)/sizeof(char*)));	

	if(0 != asCheckSet.count((char*)s.c_str())) 
		return true;

	return false;
}

bool Keywords::isDelimiterValid(const string& s)
{
	static char* asOperator[]=
	{
		"," ," ", "(", ")", "~", "#", "'", "{", "}", "[", "]",  "?", "\"",
		"\n","\r","\t"," ", ";",
		"\\", "\\\"", "\\'", "\\\\",
		"=" , "==",
		"!" , "!=",
		"%" , "%=",
		"." , ".*",
		"^" , "^=",
		"+" , "++" , "+=",
		"&" , "&&" , "&=",
		":" , "::" , "::*",
		"/" , "/=" , "/*" , "//",
		"|" , "||" , "|=",
		">" , ">>" , ">>=" , ">=",
		"<" , "<<" , "<<=" , "<=",
		"-" , "--" , "-=" , "->" , "->*",
		"*" , "*=" , "*/"
	};
	static std::set<char*, LessThan>	asDelimiter (asOperator, asOperator + (sizeof(asOperator)/sizeof(char*)));	

	if(0 != asDelimiter.count((char*)s.c_str())) 
		return true;

	return false;

}

bool Keywords::isDelimiterAmbiguous(const std::string& s)
{
	// Delimiter sequences that might be operators
	// Unproblematic ones are ,space();"~#'{}[]backslash
	// char acEndAt0[] = ", ()~#'{}[]\\?\"";

	/* Here goes!
		= ==
		! !=
		% %= 
		. .*
		^ ^=
		+ ++ +=
		& && &=
		: :: ::*
		/ /= /* //
		| || |= 
		> >> >>= >= 
		< << <<= <=
		- -- -= -> ->*
		\ \" \' \\    //These are escape sequences in literals that could get us into trouble
		* *= */ 
	// The closing comment */ tag is part of the list!!! :)
	// The smiley is not! :)

	static char acDelimiter0[] = "=!%.^+&:/*|><-\\";
	static char acDelimiter1[] = "=*+&|><";
	static char acDelimiter2[] = ""; //Nothing is ambiguous!
	static std::set<char>		xNonTerminalAt0(acDelimiter0, acDelimiter0 + sizeof(acDelimiter0));
	static std::set<char>		xNonTerminalAt1(acDelimiter1, acDelimiter1 + sizeof(acDelimiter1));
	static std::set<char>		xNonTerminalAt2(acDelimiter2, acDelimiter2 + sizeof(acDelimiter2));
	static std::set<char>*      apaNonTerminalCheckSet[] = {&xNonTerminalAt0, &xNonTerminalAt1, &xNonTerminalAt2};

	int n=s.length()-1;
	char cPopper = s[n];
	if(0 != apaNonTerminalCheckSet[n]->count(cPopper))
		return true;
	return false;
}

bool Keywords::isDataType(const std::string& s)
{
	static char* asKeywords[] = {
		"void",
		"bool",
		"char",
		"double",
		"float",
		"int",
		"long",
		"short",
		"wchar_t"
	};
	static std::set<char*, LessThan>	asCheckSet(asKeywords, asKeywords + (sizeof(asKeywords)/sizeof(char*)));	

	if(0 != asCheckSet.count((char*)s.c_str())) 
		return true;

	return false;

}

